package team.hyznrj.studentsys.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import team.hyznrj.studentsys.dto.ResultDto;
import team.hyznrj.studentsys.dto.StringListDto;
import team.hyznrj.studentsys.enums.AccountEnum;
import team.hyznrj.studentsys.exception.AccountException;
import team.hyznrj.studentsys.form.AccountForm;
import team.hyznrj.studentsys.form.RegisterForm;
import team.hyznrj.studentsys.service.AccountInfoService;
import team.hyznrj.studentsys.utils.PasswordSecurity;
import team.hyznrj.studentsys.utils.ResultUtil;

/**
 * @author ReMidDream
 * @date 2018-04-23 15:54
 **/
@RestController
@Slf4j
@RequestMapping("/account")
@Api(value = "AccountInfoController", description = "用户接口")
public class AccountInfoController {

    @Autowired
    private AccountInfoService accountInfoService;
    
    @ApiOperation(value="用户登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userAccount", value = "用户帐号",paramType = "query"),
            @ApiImplicitParam(name = "userPassword", value = "用户密码",paramType = "query"),
    })
    @PostMapping(value = "/login")
    public ResultDto<?> login(HttpServletResponse response,
                              @Valid AccountForm accountForm,
                              BindingResult bindingResult) {
            if (bindingResult.hasErrors()) {
                log.error("@登录 : 帐号或密码为空 ,accountForm={}", accountForm);
                throw new AccountException(AccountEnum.LOGIN_ERROR.getCode(),
                        bindingResult.getFieldError().getDefaultMessage());
            }
            /**2018年8月30日 ZZF修改*/
            /**2018年9月4日 权限开启时此处需开启*/
            Subject subject = SecurityUtils.getSubject();
            String username=accountForm.getUserAccount();
            String password=PasswordSecurity.getMD5(accountForm.getUserPassword(), username+"#");
    		UsernamePasswordToken token=new UsernamePasswordToken(username, password);
    		token.setRememberMe(false);
    		//登录
    		try{
    			System.out.println("登录认证....");
    			subject.login(token);
    			return accountInfoService.login(accountForm,response);
    		} //用户名不对
            catch (UnknownAccountException uae) {
            	throw new AccountException(AccountEnum.ACCOUNT_PASSWORD_NOT_CORRECT);
                //log.info("There is no user with username of " + token.getPrincipal());
            }
            //密码不对
            catch (IncorrectCredentialsException ice) {
            	throw new AccountException(AccountEnum.ACCOUNT_PASSWORD_NOT_CORRECT);
               // log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            }
            //用户被锁定
            catch (LockedAccountException lae) {
            	throw new AccountException(AccountEnum.ACCOUNT_PASSWORD_NOT_CORRECT);
                //log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                 //       "Please contact your administrator to unlock it.");
            }
            // ... catch more exceptions here (maybe custom ones specific to your application?
            //所有认证异常的父类,除了自定义继承类，否则是不会执行这里的
            catch (AuthenticationException ae) {
            	throw new AccountException(AccountEnum.ACCOUNT_PASSWORD_NOT_CORRECT);
            	//unexpected condition?  error?
            }
    }
    @ApiOperation(value="用户登出")
    @PostMapping(value = "/logout")
    public ResultDto<?> logout(HttpServletRequest request,
                               HttpServletResponse response) {
        return accountInfoService.logout(request,response);
    }
    @ApiOperation(value="用户注册")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userAccount", value = "用户帐号",paramType = "query"),
            @ApiImplicitParam(name = "userPassword", value = "用户密码",paramType = "query"),
            @ApiImplicitParam(name = "collegeId", value = "学院ID",paramType = "query"),
            @ApiImplicitParam(name = "majorId", value = "系ID <br> 院管理不需要传入",paramType = "query"),
            @ApiImplicitParam(name = "roleId", value = "角色ID",paramType = "query"),
    })
    @PostMapping(value = "/register")
    public ResultDto<?> registerAccount(@Valid RegisterForm registerForm, BindingResult bindingResult){

        if (bindingResult.hasErrors()) {
            log.error("@登录 : 参数不全 ,registerForm={}", registerForm);
            throw new AccountException(AccountEnum.LOGIN_ERROR.getCode(),
                    bindingResult.getFieldError().getDefaultMessage());
        }
        log.info("注册帐号!");
        return accountInfoService.registerAccount(registerForm);
    }

    @ApiOperation(value="删除用户")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ids", value = "帐号Ids",paramType = "query"),
    })
    @PostMapping(value = "/delete")
    public ResultDto<?> deleteAccount(@Valid StringListDto stringListDto,BindingResult bindingResult){

        if(bindingResult.hasErrors()){
            return ResultUtil.Error(AccountEnum.ACCOUNT_PASSWORD_NOT_CORRECT.getCode(),
                    bindingResult.getFieldError().getDefaultMessage());
        }
        return accountInfoService.deleteAccount(stringListDto.getIds());
    }


    @ApiOperation(value="添加/更新 角色以及操作权限关系")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "登录凭证 <br> 不填",paramType = "query"),
    })
    @PostMapping(value = "/findAccountInfo")
    public ResultDto findAccountInfo(@CookieValue(value = "token",required = false) String token){
        return  ResultUtil.Success(accountInfoService.findByAccountInfo(token));
    }

    @ApiOperation(value="修改密码")
    @PostMapping(value = "/pwdUpdate")
    public ResultDto updateAccountInfo(AccountForm accountForm,BindingResult bindingResult){
        log.info("修改密码!");
        if(bindingResult.hasErrors()){
            return ResultUtil.Error(AccountEnum.ACCOUNT_PASSWORD_NOT_CORRECT.getCode(),
                    bindingResult.getFieldError().getDefaultMessage());
        }
        return accountInfoService.updateAccountInfo(accountForm);
    }

}
